package Controller;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import Interfaz.ControllerI;
import Interfaz.EnvioDTO;
import Interfaz.ItemPlanMantenimientoDTO;
import Interfaz.RutaDTO;
import Interfaz.SucursalDTO;
import Interfaz.VehiculoDTO;
import Negocio.Cliente;
import Negocio.ClienteDTO;
import Negocio.ClienteParticular;
import Negocio.CuentaCorriente;
import Negocio.Deposito;
import Negocio.EmpresaOcasional;
import Negocio.EmpresaRegular;
import Negocio.Envio;
import Negocio.EnvioInterSucursal;
import Negocio.EnvioPuertaAPuerta;
import Negocio.ItemCuentaCorriente;
import Negocio.ItemPlanMantenimiento;
import Negocio.Ruta;
import Negocio.Sucursal;
import Negocio.Vehiculo;
import Negocio.Viaje;
import Negocio.ViajeInterSucursal;
import Persistencia.RepositoryException;
import Servicios.ServiceException;
import Servicios.ServicioClientes;
import Servicios.ServicioCuentasCorrientes;
import Servicios.ServicioDepositos;
import Servicios.ServicioEnvios;
import Servicios.ServicioItemsCuentasCorrientes;
import Servicios.ServicioRutas;
import Servicios.ServicioSucursales;
import Servicios.ServicioVehiculos;
import Servicios.ServicioViajes;

public class Controller extends UnicastRemoteObject implements ControllerI {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Vector<Envio> envios;
	private Vector<Viaje> viajes;
	private Vector<Cliente> clientes;
	private Vector<Sucursal> sucursales;
	private Vector<Ruta> rutas;
	private Vector<Vehiculo> vehiculos;
	private static Controller sistema = null;
	private TestController testSistema = null;

	private Controller() throws RemoteException {
		envios = new Vector<Envio>();
		viajes = new Vector<Viaje>();
		clientes = new Vector<Cliente>();
		sucursales = new Vector<Sucursal>();
		rutas = new Vector<Ruta>();
		vehiculos = new Vector<Vehiculo>();
		testSistema = TestController.getinstance();
	}

	public static void main(String[] args) throws Exception {
		Controller.getInstance().init();
		// Controller.getInstance().altaItemCreditoCC("cuit2", "descripcion",
		// Float.valueOf("1000.00"));
	}

	public static Controller getInstance() throws RemoteException {
		if (sistema == null) {
			sistema = new Controller();
		}
		return sistema;

	}

	private void init() {
		try {
			System.out.println("--START--");
			testSistema.CONTROLLER_TEST_CLIENTES();
			testSistema.CONTROLLER_TEST_CUENTAS_CORRIENTES();
			testSistema.CONTROLLER_TEST_SUCURSALES();
			testSistema.CONTROLLER_TEST_RUTAS();
			testSistema.CONTROLLER_TEST_VEHICULOS();
			testSistema.CONTROLLER_TEST_ENVIOS();

			System.out.println("--FIN--");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**/
	/* Crear Vehiculo */
	public void moverVehiculoASucursal(String dominio, String nombreSucursal) throws ServiceException, RemoteException {
		Vehiculo v = null;
		Sucursal s = null;
		
		if (existeVehiculo(dominio)) {
			v = buscarVehiculo(dominio);
			if (existeNombreSucursal(nombreSucursal)) {
				if(v.isEnViaje()) {
					throw new ServiceException("El vehiculo se encuentra viajando");
				}
				try {
					s = buscarSucursal(nombreSucursal);
				} catch (RepositoryException e) {
					throw new ServiceException("El vehiculo no existe");
				}
				if(s.tieneAlVehiculo(v)) {
					throw new ServiceException("El vehiculo ya se encuentra en esa sucursal");
				}

				s.recibirVehiuculoLibre(v);
				// grabar novedad en Vehiculo
				v.vehiculoRecibidoSinCargaEnSucursal(s);
				ServicioVehiculos.getInstance().guardarOActualizar(v);
				ServicioSucursales.getInstance().guardarOActualizar(s);
			} else {
				throw new ServiceException("No Existe la Sucursal");
			}
		} else {
			throw new ServiceException("No Existe el Vehiculo");
		}
		

	}

	public void altaVehiculo(String dominio, Integer tipo, float pesoTaraKG,
			float kilometrajeKM, float pesoMaximoCargaKG,
			float volumenMaximoCargaM3, boolean esRefrigerado,
			boolean estaEnGarantia) throws ServiceException {
		Vehiculo v;
		if (!existeVehiculo(dominio)) {
			v = new Vehiculo(dominio, tipo, pesoTaraKG, kilometrajeKM,
					pesoMaximoCargaKG, volumenMaximoCargaM3, esRefrigerado,
					estaEnGarantia);
			vehiculos.add(v);
			ServicioVehiculos.getInstance().guardarOActualizar(v);
		}

	}

	public Vehiculo buscarVehiculo(String dominio) throws RemoteException,
			ServiceException {
		for (Vehiculo v : vehiculos) {
			if (v.getDominio().compareTo(dominio) == 0) {
				return v;
			}
		}

		Vehiculo vehiculo;
		try {
			vehiculo = ServicioVehiculos.getInstance().getVehiculo(dominio);
			return vehiculo;
		} catch (RepositoryException e) {
			throw new ServiceException("No Existe el Vehiculo");
		}

	}

	public List<Vehiculo> getAllVehiculos() throws ServiceException,
			RemoteException {
		return ServicioVehiculos.getInstance().getVehiculos();
	}

	public boolean existeVehiculo(String dominio) {
		for (Vehiculo v : vehiculos) {

			if (v.getDominio().compareTo(dominio) == 0) {
				return true;
			}

		}
		Vehiculo vehiculo;
		try {
			vehiculo = ServicioVehiculos.getInstance().getVehiculo(dominio);
			if (vehiculo != null) {
				return true;
			}
		} catch (RepositoryException e) {
			return false;
		}// return false;*/

		return false;
	}

	/* Crear Envio */
	// TODO eliminar despues de estar seguro que el nuevo alta con el envioDTO
	// funciona
	public void altaEnvioInterSucursal(
			// Cliente
			String idCliente,
			// Origen y destino
			String nombreSucursalOrigen,
			String nombreSucursalDestino,
			// Fechas
			Date fechaRecepcion,
			Date fechaEntregaComprometida,
			Date fechaLimiteDeDespacho,
			// dato primer destinatario
			String nombreDestinatario, String apellidoDestinatario,
			String dniDestinatario,
			// datos de la Carga, sin manifiesto
			Float anchoCM, Float altoCM, Float profundidadCM, Float pesoKG,
			Float volumenM3, Integer refrigerado,// 1. Refrigerado, 2. No
													// refrigerado

			Integer fragilidad, // 1.Extremadamente fr�gil, 2.fr�gil,
								// 3.normal,4.resistente
			Integer peligrosidad,// 1.extremadamente peligroso, 2.peligroso,
									// 3.inocuo
			Integer apilable,// 0. No apilable, N.Cantidad de bultos apilables
			String especiales,// Texto de 4000 caracteres
			String manifiesto
	// sin contratos de terceros

	) throws Exception {
		Sucursal sucursalOrigen;
		Sucursal sucursalDestino;
		Cliente cliente;
		if (existeCliente(idCliente)) {
			cliente = buscarCliente(idCliente);
			if (!(nombreSucursalOrigen.compareTo(nombreSucursalDestino) == 0)) {
				if (existeNombreSucursal(nombreSucursalOrigen)) {
					sucursalOrigen = buscarSucursal(nombreSucursalOrigen);
					if (existeNombreSucursal(nombreSucursalDestino)) {
						sucursalDestino = buscarSucursal(nombreSucursalDestino);
						if (existeRuta(nombreSucursalOrigen,
								nombreSucursalDestino)) {
							EnvioInterSucursal envio = new EnvioInterSucursal(
									cliente, sucursalOrigen, sucursalDestino,
									fechaRecepcion, fechaEntregaComprometida,
									fechaLimiteDeDespacho, nombreDestinatario,
									apellidoDestinatario, dniDestinatario,
									anchoCM, altoCM, profundidadCM, pesoKG,
									volumenM3, refrigerado, fragilidad,
									peligrosidad, apilable, especiales,
									manifiesto);
							envios.add(envio);
							ServicioEnvios.getInstance().guardarOActualizar(
									envio);
							ServicioEnvios.getInstance().guardarOActualizar(
									envio);
							float precio = envio.calcularPrecio();
							if (cliente.aceptaCC()) {
								EmpresaRegular empresa = (EmpresaRegular) cliente;
								empresa.altaDebitoCC("Solicitud de envio nro "
										+ envio.getId(), precio, envio);
								ServicioCuentasCorrientes.getInstance()
										.guardarOActualizar(empresa.getCc());
							}
						} else
							throw (new Exception(
									"No existe Ruta entre esas Sucursales"));
					} else
						throw (new Exception("No existe Sucursal de destino"));
				} else
					throw (new Exception("No existe Sucursal de origen"));
			} else
				throw (new Exception(
						"No se puede crear Envio con la misma Sucursal de Origen y Destino"));
		} else
			throw (new Exception("Cliente no existe"));
	}

	public void altaEnvioInterSucursal(EnvioDTO envio) throws Exception {
		Sucursal sucursalOrigen;
		Sucursal sucursalDestino;
		Cliente cliente;
		if (existeCliente(envio.getIdCliente())) {
			cliente = buscarCliente(envio.getIdCliente());
			if (!envio.isOrigenIgualDestino()) {
				if (existeNombreSucursal(envio.getNombreSucursalOrigen())) {
					sucursalOrigen = buscarSucursal(envio
							.getNombreSucursalOrigen());
					if (existeNombreSucursal(envio.getNombreSucursalDestino())) {
						sucursalDestino = buscarSucursal(envio
								.getNombreSucursalDestino());
						if (existeRuta(envio.getNombreSucursalOrigen(),
								envio.getNombreSucursalDestino())) {
							EnvioInterSucursal envioInterSucursal = new EnvioInterSucursal(
									cliente, sucursalOrigen, sucursalDestino,
									envio);
							envios.add(envioInterSucursal);
							ServicioEnvios.getInstance().guardarOActualizar(
									envioInterSucursal);
							float precio = envioInterSucursal.calcularPrecio();
							if (cliente.aceptaCC()) {
								EmpresaRegular empresa = (EmpresaRegular) cliente;
								empresa.altaDebitoCC("Solicitud de envio nro "
										+ envioInterSucursal.getId(), precio,
										envioInterSucursal);
								ServicioCuentasCorrientes.getInstance()
										.guardarOActualizar(empresa.getCc());
								// TODO generar una factura
							}
						} else
							throw (new Exception(
									"No existe Ruta entre esas Sucursales"));
					} else
						throw (new Exception("No existe Sucursal de destino"));
				} else
					throw (new Exception("No existe Sucursal de origen"));
			} else
				throw (new Exception(
						"No se puede crear Envio con la misma Sucursal de Origen y Destino"));
		} else
			throw (new Exception("Cliente no existe"));
	}

	public void altaEnvioPuertaAPuerta(
			// Cliente
			String idCliente,
			// Origen y destino
			String calleOrigen, String numeroOrigen, String paisOrigen,
			String pisoOrigen, String departamentoOrigen,
			String entreCalle1Origen, String entreCalle2Origen,
			String localidadOrigen, String provinciaOrigen,
			String codigoPostalOrigen, String latitudOrigen,
			String longitudOrigen, String calleDestino, String numeroDestino,
			String paisDestino, String pisoDestino, String departamentoDestino,
			String entreCalle1Destino, String entreCalle2Destino,
			String localidadDestino,
			String provinciaDestino,
			String codigoPostalDestino,
			String latitudDestino,
			String longitudDestino,
			// Fechas
			Date fechaRecepcion,
			Date fechaEntregaComprometida,
			Date fechaLimiteDeDespacho,
			// dato primer destinatario
			String nombreDestinatario, String apellidoDestinatario,
			String dniDestinatario,
			// datos de la Carga, sin manifiesto
			Float anchoCM, Float altoCM, Float profundidadCM, Float pesoKG,
			Float volumenM3, Integer refrigerado,// 1. Refrigerado, 2. No
													// refrigerado
			Integer fragilidad, // 1.Extremadamente fr�gil, 2.fr�gil, 3.normal,
								// 4.resistente
			Integer peligrosidad,// 1.extremadamente peligroso, 2.peligroso,
									// 3.inocuo
			Integer apilable,// 0. No apilable, N.Cantidad de bultos apilables
			String especiales,// Texto de 4000 caracteres
			String manifiesto
	// sin contratos de terceros

	) throws Exception {
		Cliente cliente;
		if (existeCliente(idCliente)) {
			cliente = buscarCliente(idCliente);

			envios.add(new EnvioPuertaAPuerta(cliente, calleOrigen,
					numeroOrigen, paisOrigen, pisoOrigen, departamentoOrigen,
					entreCalle1Origen, entreCalle2Origen, localidadOrigen,
					provinciaOrigen, codigoPostalOrigen, latitudOrigen,
					longitudOrigen, calleDestino, numeroDestino, paisDestino,
					pisoDestino, departamentoDestino, entreCalle1Destino,
					entreCalle2Destino, localidadDestino, provinciaDestino,
					codigoPostalDestino, latitudDestino, longitudDestino,
					fechaRecepcion, fechaEntregaComprometida,
					fechaLimiteDeDespacho, nombreDestinatario,
					apellidoDestinatario, dniDestinatario, anchoCM, altoCM,
					profundidadCM, pesoKG, volumenM3, refrigerado, fragilidad,
					peligrosidad, apilable, especiales, manifiesto));
		} else
			throw (new Exception("Cliente no existe"));

	}

	/* Crear Ruta */
	public void altaRuta(String nombreSucursalOrigen,
			String nombreSucursalDestino, Float distanciaKm,
			Float duracionViajeHs, Float plazoEntregaGarantizadaHs)
			throws ServiceException, RemoteException {
		Sucursal sucursalOrigen;
		Sucursal sucursalDestino;
		if (!(nombreSucursalOrigen.compareTo(nombreSucursalDestino) == 0)) {
			if (existeNombreSucursal(nombreSucursalOrigen)) {
				sucursalOrigen = buscarSucursal2(nombreSucursalOrigen);
				if (existeNombreSucursal(nombreSucursalDestino)) {
					sucursalDestino = buscarSucursal2(nombreSucursalDestino);
					if (!existeRuta(nombreSucursalOrigen, nombreSucursalDestino)) {
						Ruta r = new Ruta(sucursalOrigen, sucursalDestino,
								distanciaKm, duracionViajeHs,
								plazoEntregaGarantizadaHs);
						rutas.add(r);
						ServicioRutas.getInstance().guardarOActualizar(r);
					} else
						throw (new ServiceException(
								"La Ruta entre estas Sucursales ya existe"));
				} else
					throw (new ServiceException("No existe Sucursal de destino"));
			} else
				throw (new ServiceException("No existe Sucursal de origen"));
		} else
			throw (new ServiceException(
					"No se puede crear ruta con la misma Sucursal de Origen y Destino"));
	}

	/* Buscar Ruta */
	public Ruta buscarRuta(String nombreSucursalOrigen,
			String nombreSucursalDestino) throws Exception {
		for (Ruta r : rutas) {
			if (r.sosEstaRura(nombreSucursalOrigen, nombreSucursalDestino))
				return r;
		}
		try {
			Ruta ruta = ServicioRutas.getInstance().getRuta(
					nombreSucursalOrigen, nombreSucursalDestino);
			if (ruta != null) {
				rutas.add(ruta);
				return ruta;
			}
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
		throw new Exception("Ruta entre Sucurasales no existe");
	}

	public boolean existeRuta(String nombreSucursalOrigen,
			String nombreSucursalDestino) {
		for (Ruta r : rutas) {
			if (r.sosEstaRura(nombreSucursalOrigen, nombreSucursalDestino))
				return true;
		}
		try {
			Ruta r = ServicioRutas.getInstance().getRuta(nombreSucursalOrigen,
					nombreSucursalDestino);
			if (r != null) {
				rutas.add(r);
				return true;
			}
		} catch (RepositoryException e) {
			e.printStackTrace();
		}

		return false;
	}

	/* Crear Sucursal */
	public void altaSucursal(String nombre, int numeroSucursal, String id,
			String calle, String numero, String pais, String piso,
			String departamento, String entreCalle1, String entreCalle2,
			String localidad, String provincia, String codigoPostal,
			String latitud, String longitud) throws RemoteException,
			ServiceException {

		if (!existeNombreSucursal(nombre)) {
			if (!existeIdSucursal(id)) {
				Sucursal s = new Sucursal(nombre, numeroSucursal, id, calle,
						numero, pais, piso, departamento, entreCalle1,
						entreCalle2, localidad, provincia, codigoPostal,
						latitud, longitud);
				sucursales.add(s);
				ServicioSucursales.getInstance().guardarOActualizar(s);
			} else
				throw new ServiceException("Ya existe Sucursal con ese id");
		} else
			throw new ServiceException("Ya existe Sucursal con ese nombre");
	}

	public List<SucursalDTO> getAllSucursales() throws RemoteException,
			ServiceException {
		List<SucursalDTO> sucursalesDTO = new ArrayList<SucursalDTO>();
		try {
			List<Sucursal> sucursales = ServicioSucursales.getInstance()
					.getSucursales();
			for (Sucursal sucursal : sucursales) {
				sucursalesDTO.add(sucursal.getDTO());
			}
			return sucursalesDTO;
		} catch (ServiceException e) {
			e.printStackTrace();
		}
		throw new ServiceException("Error al buscar las sucursales");

	}

	/* Buscar Sucursal */
	private Sucursal buscarSucursal(String nombre) throws ServiceException,
			RepositoryException {
		for (Sucursal s : sucursales) {
			if (nombre.compareTo(s.getNombre()) == 0)
				return s;
		}
		try {
			Sucursal s = ServicioSucursales.getInstance().getSucursalPorNombre(
					nombre);
			if (s != null) {
				sucursales.add(s);
				return s;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		throw new ServiceException("Sucursal no existe");
	}
	
	/*Nuevo busqueda sucursal con ServiceException*/
	private Sucursal buscarSucursal2(String nombre) throws ServiceException,
		RemoteException {
		for (Sucursal s : sucursales) {
			if (nombre.compareTo(s.getNombre()) == 0)
				return s;
		}
		try {
			Sucursal s = ServicioSucursales.getInstance().getSucursalPorNombre(
					nombre);
			if (s != null) {
				sucursales.add(s);
				return s;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		throw new ServiceException("Sucursal no existe");
	}

	public Sucursal getSucursal(String id) throws ServiceException,
			RemoteException {
		for (Sucursal s : sucursales) {
			if (id.compareTo(s.getId()) == 0)
				return s;
		}
		try {
			Sucursal s = ServicioSucursales.getInstance().getSucursal(id);
			if (s != null) {
				sucursales.add(s);
				return s;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		throw new ServiceException("Sucursal no existe");
	}

	private boolean existeNombreSucursal(String nombre) {
		for (Sucursal s : sucursales) {
			if (nombre.compareTo(s.getNombre()) == 0)
				return true;
		}
		try {
			Sucursal s = ServicioSucursales.getInstance().getSucursalPorNombre(
					nombre);
			if (s != null) {
				sucursales.add(s);
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	private boolean existeIdSucursal(String id) {
		for (Sucursal s : sucursales) {
			if (id.compareTo(s.getId()) == 0)
				return true;
		}
		return false;
	}

	/**
	 * Alta de Item Credito en Cuenta Corriente
	 * 
	 * @param cuit
	 * @param descripcion
	 * @param importeMovimiento
	 * @throws Exception
	 */
	public void altaItemCreditoCC(String cuit, String descripcion,
			Float importeMovimiento) throws RemoteException, ServiceException {
		try {
			Cliente cliente = sistema.buscarCliente(cuit);
			if (cliente.aceptaCC()) {
				EmpresaRegular empresaRegular = (EmpresaRegular) cliente;
				empresaRegular.altaCreditoCC(descripcion, importeMovimiento);
				CuentaCorriente cuentaCorriente = empresaRegular.getCc();
				ServicioCuentasCorrientes.getInstance().guardarOActualizar(
						cuentaCorriente);
			} else
				throw (new ServiceException("Cliente no tiene Cuenta Corriente"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void altaItemDebitoCC(String cuit, String descripcion,
			Float importeMovimiento, Envio envio) throws Exception {
		try {
			Cliente c = sistema.buscarCliente(cuit);
			if (c.aceptaCC()) {
				EmpresaRegular e = (EmpresaRegular) c;
				e.altaDebitoCC(descripcion, importeMovimiento, envio);
				ServicioCuentasCorrientes.getInstance().guardarOActualizar(
						e.getCc());
			} else {
				throw new Exception("El Cliente no tiene Cuenta Corriente");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void altaClienteParticular(ClienteDTO clienteDTO)
			throws RemoteException {
		this.altaClienteParticular(clienteDTO.getNombre(),
				clienteDTO.getApellido(), clienteDTO.getDni(),
				clienteDTO.getCalle(), clienteDTO.getNumero(),
				clienteDTO.getPais(), clienteDTO.getPiso(),
				clienteDTO.getDepartamento(), clienteDTO.getEntreCalle1(),
				clienteDTO.getEntreCalle2(), clienteDTO.getLocalidad(),
				clienteDTO.getProvincia(), clienteDTO.getCodigoPostal(),
				clienteDTO.getLatitud(), clienteDTO.getLongitud());
	}

	/* Alta Cliente Particular */
	public void altaClienteParticular(String nombre, String apellido,
			String dni, String calle, String numero, String pais, String piso,
			String departamento, String entreCalle1, String entreCalle2,
			String localidad, String provincia, String codigoPostal,
			String latitud, String longitud) throws RemoteException {

		try {
			if (!sistema.existeCliente(dni)) {
				ClienteParticular c = new ClienteParticular(nombre, apellido,
						dni, calle, numero, pais, piso, departamento,
						entreCalle1, entreCalle2, localidad, provincia,
						codigoPostal, latitud, longitud);
				clientes.add(c);
				ServicioClientes.getInstance().guardarOActualizar(c);
			} else {
				throw new Exception("Cliente ya existe con ese Numero de DNI");
			}
		} catch (RemoteException e) {
			e.printStackTrace();
			throw (e);
		} catch (ServiceException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// Alta Empresa Regular
	public void altaEmpresaRegular(String cuit, String razonSocial,
			String calle, String numero, String pais, String piso,
			String departamento, String entreCalle1, String entreCalle2,
			String localidad, String provincia, String codigoPostal,
			String latitud, String longitud, Float limiteDeCredito)
			throws Exception {
		try {
			if (!sistema.existeCliente(cuit)) {
				EmpresaRegular er = new EmpresaRegular(cuit, razonSocial,
						calle, numero, pais, piso, departamento, entreCalle1,
						entreCalle2, localidad, provincia, codigoPostal,
						latitud, longitud, limiteDeCredito);
				clientes.add(er);
				ServicioClientes.getInstance().guardarOActualizar((Cliente) er);
			} else {
				throw new Exception("Cliente ya existe con ese Numero de CUIT "
						+ cuit);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw (e);
		}
	}

	public void altaEmpresaRegular(ClienteDTO clienteDTO, Float limiteDeCredito)
			throws RemoteException, ServiceException {
		try {
			if (!sistema.existeCliente(clienteDTO.getCuit())) {
				EmpresaRegular er = new EmpresaRegular(clienteDTO.getCuit(),
						clienteDTO.getRazonSocial(), clienteDTO.getCalle(),
						clienteDTO.getNumero(), clienteDTO.getPais(),
						clienteDTO.getPiso(), clienteDTO.getDepartamento(),
						clienteDTO.getEntreCalle1(),
						clienteDTO.getEntreCalle2(), clienteDTO.getLocalidad(),
						clienteDTO.getProvincia(),
						clienteDTO.getCodigoPostal(), clienteDTO.getLatitud(),
						clienteDTO.getLongitud(), limiteDeCredito);
				clientes.add(er);
				ServicioClientes.getInstance().guardarOActualizar((Cliente) er);
			} else {
				throw new ServiceException(
						"Cliente ya existe con ese Numero de CUIT "
								+ clienteDTO.getCuit());
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServiceException(e.getMessage());
		}
	}

	// Alta Empresa Ocasional
	public void altaEmpresaOcasional(String cuit, String razonSocial,
			String calle, String numero, String pais, String piso,
			String departamento, String entreCalle1, String entreCalle2,
			String localidad, String provincia, String codigoPostal,
			String latitud, String longitud) throws Exception {
		try {
			if (!sistema.existeCliente(cuit)) {
				EmpresaOcasional eo = new EmpresaOcasional(cuit, razonSocial,
						calle, numero, pais, piso, departamento, entreCalle1,
						entreCalle2, localidad, provincia, codigoPostal,
						latitud, longitud);
				clientes.add(eo);
			} else {
				throw new Exception("Cliente ya existe con ese Numero de CUIT");
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw (e);
		}
	}

	// Buscar Cliente de cualquier tipo
	public Cliente buscarCliente(String id) throws Exception {
		for (Cliente c : clientes) {
			if (id.compareTo(c.getClienteId()) == 0)
				return c;
		}
		try {
			Cliente c = ServicioClientes.getInstance().getCliente(id);
			if (c != null) {
				clientes.add(c);
				return c;
			}
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
		throw new Exception("Cliente no existe");
	}

	// Verificacion si Cliente Existe
	public boolean existeCliente(String id) {
		for (Cliente c : clientes) {
			if (id.compareTo(c.getClienteId()) == 0)
				return true;
		}

		try {
			Cliente cliente = ServicioClientes.getInstance().getCliente(id);
			if (cliente != null) {
				clientes.add(cliente);
				return true;
			}
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
		return false;
	}

	public EnvioDTO getEnvioInterSucursal(int envioId) throws RemoteException,
			ServiceException {
		EnvioDTO envioDTO = new EnvioDTO();
		try {
			Envio envio = ServicioEnvios.getInstance().getEnvio(envioId);
			envioDTO = envio.getDTO();
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
		return envioDTO;
	}

	public EnvioInterSucursal getEnvioIS(int envioId) throws RemoteException,
			ServiceException {
		EnvioInterSucursal envio = null;
		try {
			envio = (EnvioInterSucursal) ServicioEnvios.getInstance().getEnvio(
					envioId);
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
		return envio;
	}

	public List<EnvioDTO> getEnviosInterSucursal() throws RemoteException,
			ServiceException {
		List<EnvioDTO> enviosDTO = new ArrayList<EnvioDTO>();
		List<Envio> envios = ServicioEnvios.getInstance().getEnvios();
		for (Envio envio : envios) {
			enviosDTO.add(envio.getDTO());
		}
		return enviosDTO;
	}

	public float getTiempoViaje(String nombreSucursalOrigen,
			String nombreSucursalDestino) throws Exception {
		if (existeRuta(nombreSucursalOrigen, nombreSucursalDestino)) {
			Ruta r = buscarRuta(nombreSucursalOrigen, nombreSucursalDestino);
			return r.getDuracionViajeHs();
		} else
			throw (new Exception("No existe Ruta entre esas Sucursales"));
	}

	public void altaViajeInterSucursal(Sucursal sucursalOrigen,
			Sucursal sucursalDestino, Vehiculo vehiculoMasPequeno,
			List<Envio> estosEnvios) throws RemoteException, Exception {
		ViajeInterSucursal v = new ViajeInterSucursal(sucursalOrigen,
				sucursalDestino, vehiculoMasPequeno, estosEnvios);
		viajes.add(v);
		vehiculoMasPequeno.setEnViaje(true);
		for (Envio envio : estosEnvios) {
			envio.setEnViaje(true);
		}
		ServicioViajes.getInstance().guardarOActualizar(v);
		vehiculoMasPequeno.vehiculoDespachadoConCargaASucursal(v);
		ServicioVehiculos.getInstance().guardarOActualizar(vehiculoMasPequeno);
	}

	@Override
	public void altaVehiculo(VehiculoDTO dto) throws RemoteException,
			ServiceException {
		this.altaVehiculo(dto.getDominio(), dto.getTipo(), dto.getPesoTaraKG(),
				dto.getKilometrajeKM(), dto.getPesoMaximoCargaKG(),
				dto.getVolumenMaximoCargaM3(), dto.isEsRefrigerado(),
				dto.isEstaEnGarantia());
	}
	
	@Override
	public void altaSucursal(SucursalDTO dto) throws RemoteException,
			ServiceException {
		this.altaSucursal(	dto.getNombre(), dto.getNumeroSucursal(), dto.getId(),
							dto.getCalle(), dto.getNumero(), dto.getPais(), dto.getPiso(),
							dto.getDepartamento(), dto.getEntreCalle1(), dto.getEntreCalle2(),
							dto.getLocalidad(), dto.getProvincia(), dto.getCodigoPostal(),
							dto.getLatitud(), dto.getLongitud());
	}
	
	@Override
	public void altaRuta(RutaDTO dto) throws RemoteException,
			ServiceException {
		
			this.altaRuta(	dto.getNombreSucursalOrigen(), dto.getNombreSucursalDestino(),
							dto.getDistanciaKm(), dto.getDuracionViajeHs(),
							dto.getPlazoEntregaGarantizadaHs());

	}

	@Override
	public List<Cliente> getAllClientes() throws RemoteException {
		List<Cliente> clientes = null;
		try {
			clientes = ServicioClientes.getInstance().getClientes();
		} catch (ServiceException e) {
			throw (new RemoteException(
					"Ocurrio un problema al buscar todos los clientes"));
		}
		return clientes;
	}

	@Override
	public CuentaCorriente getCuentaCorriente(int cuentaCorrienteId)
			throws RemoteException, ServiceException {
		CuentaCorriente cc = null;
		try {
			cc = ServicioCuentasCorrientes.getInstance().getCuentaCorrienta(
					cuentaCorrienteId);
		} catch (RepositoryException e) {
			throw (new ServiceException(
					"Ocurrio un error al consultar la cuenta corriente "
							+ cuentaCorrienteId));
		}

		return cc;
	}

	@Override
	public List<ItemCuentaCorriente> getItemsCuentaCorriente(
			int cuentaCorrienteId) throws RemoteException, ServiceException {
		List<ItemCuentaCorriente> items = null;
		try {
			items = ServicioItemsCuentasCorrientes.getInstance()
					.getItemsCuentaCorrienta(cuentaCorrienteId);
		} catch (RepositoryException e) {
			e.printStackTrace();
			throw new ServiceException(
					"Ocurrio un error al buscar los items de la cuenta "
							+ cuentaCorrienteId);
		}

		return items;
	}

	public void altaItemMantenimientoVehiculo(String dominio,
			ItemPlanMantenimientoDTO itemDTO) throws RemoteException,
			ServiceException {
		try {
			Vehiculo vehiculo = buscarVehiculo(dominio);
			ItemPlanMantenimiento item = new ItemPlanMantenimiento(itemDTO);
			item.setKmVehiculoFechaCreacion(vehiculo.getKilometrajeKM());
			vehiculo.agregarMantenimiento(item);
			ServicioVehiculos.getInstance().guardarOActualizar(vehiculo);
		} catch (ServiceException e) {
			throw new ServiceException("No existe el vehiculo con dominio "
					+ dominio);
		}
	}

	@Override
	public List<Viaje> getAllViajes() throws RemoteException, ServiceException {
		List<Viaje> viajes = ServicioViajes.getInstance().getViajes();
		return viajes;
	}

	@Override
	public Viaje getViaje(int viajeId) throws RemoteException, ServiceException {
		Viaje viaje;
		try {
			viaje = ServicioViajes.getInstance().getViaje(viajeId);
		} catch (RepositoryException e) {
			e.printStackTrace();
			throw new ServiceException(
					"Ocurrio un error al consultar el viaje " + viajeId);
		}
		return viaje;
	}

	/**
	 * - Movemos todos los envios en los depositos de la sucursal de destino -
	 * Movemos el vehiculo a la sucursal de destino
	 */
	public void recibirViaje(int viajeId) throws RemoteException,
			ServiceException {
		Viaje viaje = this.getViaje(viajeId);
		ViajeInterSucursal viajeIntersucursal = (ViajeInterSucursal) viaje;// solo
																			// manejamos
																			// viajes
																			// intersucursales,
																			// no
																			// va
																			// a
																			// dar
																			// error
		viajeIntersucursal.entregado();// se marca el viaje como entregado y la
										// fecha real de llegada
		try {
			viajeIntersucursal.getSucursalDestino().recepcionarEnvioEnDestino(
					viajeIntersucursal);
		} catch (Exception e) {
			throw new ServiceException("No hay depositos disponibles para los envios recibidos");
		}// se mueve el vehiculo a la sucursal, los
									// envios pasan a estar recibidos
		ServicioViajes.getInstance().guardarOActualizar(viajeIntersucursal);
		this.guardarSucursal(viajeIntersucursal.getSucursalDestino());
	}

	public void guardarSucursal(Sucursal sucursal) {
		try {
			ServicioSucursales.getInstance().guardarOActualizar(sucursal);
		} catch (ServiceException e) {
			e.printStackTrace();
		}
	}

	public void guardarEnvio(Envio envio) {
		try {
			ServicioEnvios.getInstance().guardarOActualizar(envio);
		} catch (ServiceException e) {
			e.printStackTrace();
		}

	}

	@Override
	public void entregarEnvio(int envioId) throws RemoteException,
			ServiceException {
		EnvioInterSucursal envio = this.getEnvioIS(envioId);
		envio.entregado();
		this.guardarEnvio(envio);
		this.guardarSucursal(envio.getSucursalDestino());
	}
}
